﻿#include "GLLInc.h"
#include "GLLLevel.h"
#include "GLLLevelThread.h"
#include "GLLTimer.h"
#include "GLLSignal.h"

namespace GLL
{
#define LOCK_LIST	LOCK_MUTEX(_listMutex)

	//-----------------------------------------------------------------------------
	struct LevelThreadFunctionArg
	{
		LevelThread* pLT;
		Signal* pSgn;
	};

	void LevelThreadFunction(void* ptr)
	{
		LevelThreadFunctionArg* pArg = (LevelThreadFunctionArg*)ptr;
		pArg->pLT->TheThread(*pArg->pSgn);
	}

	void LevelThread::Continue()
	{
		if( _1Thread ) return;
		//_loadingQueueFinished.notify_one();
	}

	void LevelThread::Start()
	{
		if( _1Thread ) return;

		Signal signal;
		_Level->_OnLoadingBegin_spec(GetThreadType());

		//_beginthread();
		_threadInstance = GLL_NEW boost::thread(boost::bind(&LevelThread::TheThread, this, boost::ref(signal)));

		//主线等待信号，当线程启动以后，主线就可以马上继续了。
		signal.Wait();
		_Level->_OnLoadingEnd_spec(GetThreadType());
	}

	void LevelThread::TheThread( Signal& signal)
	{
		if( _1Thread ) return;

		_Level->_OnLoadingThreadBegin_spec(GetThreadType());
		//主线可以继续了
		signal.Notify();

#ifdef GLL_DEBUG
		SetName();
#endif
 
		//不停的读取 创建
		while(!_threadFinished)
		{
			Do();
			Timer::Sleep(100);
			//boost::this_thread::sleep(boost::posix_time::milliseconds(200));
			//_loadingQueueFinished.wait(thread_lock);
		}
		Clear();
		_Level->_OnLoadingThreadEnd_spec(GetThreadType());
	}

	void LevelThread::WaitingFinished()
	{
		//已经被finished了
		if(_threadFinished) return;
		_threadFinished = true;
		//_loadingQueueFinished.notify_one();

		//等待创建/删除线程退出
		if(_threadInstance)
		{
			_threadInstance->join();
			GLL_DEL(_threadInstance);
			_threadInstance = nullptr;
		}

		//不是多线程时，主动清理。多线程时，交给线程处理
		if( _1Thread ){
			Clear();
		}
	}

	void LevelThread::Do()
	{
		GLL_Try;
		do
		{
			if(_threadFinished)
				break; 
			DoOnce();
		}while( QueueSize() );
		GLL_Catch;
	}

	void LevelThread::Clear()
	{
		//后续动作必须执行
		do
		{
			DoOnce();
		}while( QueueSize() );
	}

	bool LevelThread::PutToQueue( LvlObjSrdPtr  ptr)
	{
		if( ! PrePut(ptr) ) return false;
		LOCK_LIST;
		_objQueue.push_back(ptr);
		Continue();
		return true;
	}

	GLL::LvlObjSrdPtr LevelThread::PopObj()
	{
		LvlObjSrdPtr obj;
		LOCK_LIST;
		if(QueueSize() == 0) return obj;
		obj = _objQueue.front();
		//放弃所有权
		_objQueue.pop_front();
		return obj;
	}

	int LevelThread::QueueSize()
	{
		LOCK_LIST;
		return _objQueue.size();
	}

	//-----------------------------------------------------------------------------
	//PRE
	bool LevelThreadPreLoad::DoOnce()
	{
		LvlObjSrdPtr obj = PopObj();
		if(!obj) return false;

		if( ! obj->HasLifeStatus(LvlObj::LS_Created)){
			//还没有创建。直接返回
			return false;
		}

		obj->SetLifeStatus(LvlObj::LS_PreLoading);
		obj->_PreLoad();
		obj->SetLifeStatus(LvlObj::LS_PreLoaded);
		obj->RemoveLifeStatus(LvlObj::LS_PreLoading);

		LevelThreadLoad* pTL = _Level->GetLoadingThread();
		if(!pTL) return false;
		if( ! pTL->PutToQueue(obj) )
		{
			_Level->PutToUnloadQueue(obj->GetID());
		}

		return true;
	}

	//-----------------------------------------------------------------------------
	//LOAD:
	bool LevelThreadLoad::DoOnce()
	{
		LvlObjSrdPtr obj = PopObj();
		if(!obj) return false;

		obj->SetLifeStatus(LvlObj::LS_Loading);
		obj->_DoLoad();
		obj->SetLifeStatus(LvlObj::LS_Loaded);
		obj->RemoveLifeStatus(LvlObj::LS_Loading);

		_Level->_ploadThread.PutToQueue(obj);
		return true;
	}

	//-----------------------------------------------------------------------------
	//post Load
	bool LevelThreadPostLoad::DoOnce()
	{
		LvlObjSrdPtr obj = PopObj();
		if(!obj) return false;

		obj->_PostLoad();
		if(_Level->_event) _Level->_event->OnObjectLoaded(obj.get());
		return true;
	}

	//-----------------------------------------------------------------------------
	//UNLOAD:
	bool LevelThreadUnload::DoOnce()
	{
		LvlObjSrdPtr obj = PopObj();
		if(!obj) return false;

		//正在读取的，被取消了，等待读取结束
		if( obj->HasLifeStatus(LvlObj::LS_Loading) )
		{
			PutToQueue(obj);
			return false;
		}

		obj->SetLifeStatus(LvlObj::LS_Unloading);
		obj->_DoUnload();
		obj->SetLifeStatus(LvlObj::LS_Unloaded);
		obj->RemoveLifeStatus(LvlObj::LS_Unloading);

		_Level->_postThread.PutToQueue(obj);

		return false;
	}

	//-----------------------------------------------------------------------------
	//POST
	bool LevelThreadPost::DoOnce()
	{
		LvlObjSrdPtr obj = PopObj();
		if(!obj) return false;

		obj->SetLifeStatus(LvlObj::LS_PostUnloading);
		obj->_PostUnload();
		obj->SetLifeStatus(LvlObj::LS_Over);
		obj->RemoveLifeStatus(LvlObj::LS_PostUnloading);

		//通知回调
		if(_Level->_event) _Level->_event->OnObjectDeleted(obj.get());
		return true;
	}





};//GLL

